package com.xjrsoft.module.taskSchedule.service.impl;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xjrsoft.common.allenum.TsEndTypeEnum;
import com.xjrsoft.common.allenum.TsStartTypeEnum;
import com.xjrsoft.common.allenum.TsStateEnum;
import com.xjrsoft.common.helper.TsHelper;
import com.xjrsoft.common.page.ConventPage;
import com.xjrsoft.common.page.PageOutput;
import com.xjrsoft.common.tsmodel.TsSchemeModel;
import com.xjrsoft.core.constant.AppConstant;
import com.xjrsoft.core.tool.utils.StringPool;
import com.xjrsoft.core.tool.utils.StringUtil;
import com.xjrsoft.module.taskSchedule.dto.GetTsPageListDto;
import com.xjrsoft.module.taskSchedule.dto.SavedSchemeInfoDto;
import com.xjrsoft.module.taskSchedule.entity.XjrTsProcess;
import com.xjrsoft.module.taskSchedule.entity.XjrTsScheme;
import com.xjrsoft.module.taskSchedule.entity.XjrTsSchemeInfo;
import com.xjrsoft.module.taskSchedule.mapper.XjrTsProcessMapper;
import com.xjrsoft.module.taskSchedule.service.IXjrTsProcessService;
import com.xjrsoft.module.taskSchedule.service.IXjrTsSchemeInfoService;
import com.xjrsoft.module.taskSchedule.service.IXjrTsSchemeService;
import com.xjrsoft.module.taskSchedule.vo.GetTsPageListVo;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 任务调度表 服务实现类
 * </p>
 *
 * @author jobob
 * @since 2020-11-10
 */
@Service
public class XjrTsProcessServiceImpl extends ServiceImpl<XjrTsProcessMapper, XjrTsProcess> implements IXjrTsProcessService {

    @Autowired
    private  IXjrTsSchemeInfoService schemeInfoService;
    @Autowired
    private  IXjrTsSchemeService schemeService;

    @Override
    public PageOutput<GetTsPageListVo> getPageList(GetTsPageListDto dto) {

        String keyword = dto.getKeyword();
        if (!StringUtil.isBlank(keyword)) {
            keyword = StringPool.PERCENT + keyword + StringPool.PERCENT;
        }

        IPage<GetTsPageListVo> page = ConventPage.getPage(dto);

        List<GetTsPageListVo> schemeInfoVoList = baseMapper.getPageList(keyword, page);

        return ConventPage.getPageOutput(page.getTotal(), schemeInfoVoList);
    }

    @Override
    @Transactional
    @SneakyThrows
    public Boolean addTs(String processId, XjrTsSchemeInfo schemeInfo, XjrTsScheme scheme) {
        String schemeInfoId = IdWorker.get32UUID();
        schemeInfo.setId(schemeInfoId);
        scheme.setId(IdWorker.get32UUID());
        scheme.setSchemeInfoId(schemeInfoId);
        scheme.setIsActive(1);
        if (!schemeInfoService.save(schemeInfo) || !schemeService.save(scheme)) {
            return false;
        }

        TsSchemeModel tsSchemeModel = JSONObject.parseObject(scheme.getScheme(), TsSchemeModel.class);
        XjrTsProcess process = new XjrTsProcess();
        process.setId(processId);
        process.setState(TsStateEnum.NOTRUN.getCode());
        process.setSchemeId(scheme.getId());
        process.setSchemeInfoId(schemeInfoId);
        process.setEndType(tsSchemeModel.getEndType());
        process.setEndTime(tsSchemeModel.getEndTime());

        if (tsSchemeModel.getStartType() == TsStartTypeEnum.RUN.getCode()) {
            process.setState(TsStateEnum.RUN.getCode());
            process.setBeginTime(LocalDateTime.now());
        } else {
            process.setBeginTime(tsSchemeModel.getStartTime());
        }
        process.setEndTime(tsSchemeModel.getEndTime());

        return this.save(process);
    }

    @Override
    @SneakyThrows
    @Transactional
    public Boolean updateTs(XjrTsProcess process, XjrTsSchemeInfo schemeInfo, XjrTsScheme scheme) {
        Integer state = process.getState();
        if (process == null){
            throw new Exception("找不到当前任务！");
        }

        //更新模板信息
        schemeInfo.setId(process.getSchemeInfoId());
        //更新模版
        scheme.setId(process.getSchemeId());
        if (!schemeInfoService.updateById(schemeInfo)) {
            return false;
        }

        TsSchemeModel tsSchemeModel = JSONUtil.toBean(scheme.getScheme(), TsSchemeModel.class);
        LocalDateTime startTime = tsSchemeModel.getStartTime();
        if (startTime == null && tsSchemeModel.getStartType() == 1) {
            process.setState(TsStateEnum.RUN.getCode());
            process.setBeginTime(LocalDateTime.now());
        } else {
            process.setBeginTime(startTime);
        }
        process.setEndType(tsSchemeModel.getEndType());
        process.setEndTime(tsSchemeModel.getEndTime());

        boolean isSuccess = false;
        if (state != null && state == 4) {
            String oldSchemeId = scheme.getId();
            String schemeId = IdWorker.get32UUID();
            scheme.setId(schemeId);
            process.setSchemeId(schemeId);
            process.setId(IdWorker.get32UUID());
            process.setCreateDate(LocalDateTime.now());
            isSuccess = this.save(process) && schemeService.save(scheme) && schemeService.updateState(oldSchemeId, 2);
        } else {
            isSuccess = this.updateById(process) && schemeService.updateById(scheme);
        }

        return isSuccess;
    }

    @Override
    public Boolean deleteTs(String id, String schemeInfoId) {
        TsHelper.deleteJob(id);
        if (this.count(Wrappers.<XjrTsProcess>query().lambda().eq(XjrTsProcess::getSchemeInfoId, schemeInfoId)) <= 1) {
            schemeInfoService.removeById(schemeInfoId);
        }
        return this.removeById(id);
    }

    @Override
    @SneakyThrows
    @Transactional
    public Boolean startTs(String id) {
        boolean exists = TsHelper.checkExists(id, AppConstant.APPLICATION_GROUP_NAME);
        boolean isSuccess = this.updateState(id, 2);
        if (isSuccess) {
            if (exists) {
                TsHelper.deleteJob(id);
            }
            XjrTsProcess process = this.getById(id);
            XjrTsScheme scheme = schemeService.getById(process.getSchemeId());
            log.trace(scheme.getScheme());
            TsSchemeModel tsSchemeModel = JSONUtil.toBean(scheme.getScheme(), TsSchemeModel.class);
            TsHelper.addJob(id, tsSchemeModel);
        }
        return isSuccess;
    }

    @Override
    public Boolean stopTask(String id) {
        TsHelper.pauseJob(id);
        return this.updateState(id, 3);
    }

    public boolean updateState(String id, Integer state) {
        XjrTsProcess updateProcess = new XjrTsProcess();
        updateProcess.setId(id);
        updateProcess.setState(state);
        return this.updateById(updateProcess);
    }
}
